package com.example.hibernate.demo.service;

import com.example.hibernate.demo.entity.Employee;
import com.example.hibernate.demo.entity.Project;
import com.example.hibernate.demo.repository.EmployeeRepository;
import com.example.hibernate.demo.repository.ProjectRepository;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
@RequiredArgsConstructor
public class EmployeeService {
    
    private final EmployeeRepository employeeRepository;
    private final ProjectRepository projectRepository;
    
    @Transactional(readOnly = true)
    public List<Employee> findAll() {
        return employeeRepository.findAll();
    }
    
    @Transactional(readOnly = true)
    public Employee findById(Long id) {
        return employeeRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with id: " + id));
    }
    
    @Transactional(readOnly = true)
    public Employee findByEmail(String email) {
        return employeeRepository.findByEmail(email)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with email: " + email));
    }
    
    @Transactional(readOnly = true)
    public List<Employee> findByDepartmentId(Long departmentId) {
        return employeeRepository.findByDepartmentId(departmentId);
    }
    
    @Transactional(readOnly = true)
    public List<Employee> findBySalaryRange(BigDecimal minSalary, BigDecimal maxSalary) {
        return employeeRepository.findBySalaryRange(minSalary, maxSalary);
    }
    
    @Transactional(readOnly = true)
    public Page<Employee> findByStatus(Employee.EmployeeStatus status, Pageable pageable) {
        return employeeRepository.findByStatus(status, pageable);
    }
    
    @Transactional
    public Employee save(Employee employee) {
        return employeeRepository.save(employee);
    }
    
    @Transactional
    public Employee update(Long id, Employee employeeDetails) {
        Employee employee = findById(id);
        employee.setFirstName(employeeDetails.getFirstName());
        employee.setLastName(employeeDetails.getLastName());
        employee.setEmail(employeeDetails.getEmail());
        employee.setSalary(employeeDetails.getSalary());
        employee.setStatus(employeeDetails.getStatus());
        return employeeRepository.save(employee);
    }
    
    @Transactional
    public void delete(Long id) {
        Employee employee = findById(id);
        employeeRepository.delete(employee);
    }
    
    @Transactional
    public Employee assignToProject(Long employeeId, Long projectId) {
        Employee employee = employeeRepository.findById(employeeId)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with id: " + employeeId));
        
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new EntityNotFoundException("Project not found with id: " + projectId));
        
        employee.addProject(project);
        return employeeRepository.save(employee);
    }
    
    @Transactional
    public Employee removeFromProject(Long employeeId, Long projectId) {
        Employee employee = employeeRepository.findByIdWithProjects(employeeId)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with id: " + employeeId));
        
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> new EntityNotFoundException("Project not found with id: " + projectId));
        
        employee.removeProject(project);
        return employeeRepository.save(employee);
    }
}